﻿using CoachingOrganizer.Logic.Common;
using CoachingOrganizer.Logic.Helpers;
using CoachingOrganizer.Logic.Logic.Common;
using CoachingOrganizer.Toolkit.Events;
using CoachingOrganizer.Toolkit.Patterns;
using CoachingOrganizer.Toolkit.Threading.CollectionsDecorators;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CoachingOrganizer.Logic.Models.Common
{
    public class InteractionModel : DisposableObject
    {
        private readonly InteractionLogic _logic;
        private readonly SimpleCollectionLoadDecorator<PeriodModel> _periods;
        private PeriodModel _currentPeriod;

        public PeriodModel CurrentPeriod
        {
            get { return _currentPeriod; }
            set
            {
                _currentPeriod = value;
                OnCurrentPeriodChanged();
            }
        }

        public IEnumerable<PeriodModel> Periods
        {
            get { return _periods.Items; }
        }

        public event EventHandler PeriodsChanged
        {
            add { _periods.ItemsChanged += value; }
            remove { _periods.ItemsChanged -= value; }
        }

        public event NotifyCollectionChangedEventHandler PeriodsCollectionChanged
        {
            add { _periods.ItemsCollectionChanged += value; }
            remove { _periods.ItemsCollectionChanged -= value; }
        }

        public event EventHandler CurrentPeriodChanged;

        internal Func<ActionResult<IEnumerable<PeriodLogic>>> EnumeratePeriodsDelegate;

        internal Func<ActionResult<PeriodLogic>> AddNewPeriodDelegate;

        public InteractionModel(LogicExtender extender)
        {
            _logic = new InteractionLogic(this, extender);
            _periods = new SimpleCollectionLoadDecorator<PeriodModel>(EnumeratePeriods);
        }

        public async Task LoadPeriodsAsync(System.Threading.CancellationToken cancelLoad)
        {
            await Task.Run(() => _periods.FillItemsList(), cancelLoad);
        }

        public async Task<ActionResult> AddNewPeriod()
        {
            return await Task.Run(() =>
            {
                ActionResult<PeriodModel> newPeriodResult = UpdateHelper.GetModel(AddNewPeriodDelegate, l => l.Model);
                if (newPeriodResult.IsValid)
                    _periods.ModifyCollection(col => col.Add(newPeriodResult.Result));
                return newPeriodResult.IsValid ? ActionResult.ValidResult : ActionResult.GetErrorResult(newPeriodResult);
            });
        }

        public void ModifyPeriodsCollection(Action<IList<PeriodModel>> modificationDelegate)
        {
            _periods.ModifyCollection(modificationDelegate);
        }

        private ActionResult<IEnumerable<PeriodModel>> EnumeratePeriods()
        {
            return UpdateHelper.EnumerateModels(EnumeratePeriodsDelegate, l => l.Model);
        }

        protected override void DisposeManagedResources()
        {
            base.DisposeManagedResources();
            _logic.Dispose();
        }

        protected virtual void OnCurrentPeriodChanged()
        {
            EventHandler handler = CurrentPeriodChanged;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }
    }
}
